module LCD_DrawPoint(
       input         clk,
		 input         rst_n,
		 input [9:0]   x_start,//横坐标起始
		 input [9:0]   x_end,  //横坐标结束
		 input [9:0]   y_start,//纵坐标起始
		 input [9:0]   y_end,  //纵坐标起始
		 input [15:0]  color,//RGB565
		 input         sop,
		 input         write_en,//high active,一个clk周期的高电平触发一帧
		 output        write_ready,//write_en拉高后必须等待write_ready为高才表示
		 output [17:0] index
);
parameter CMD_NOP = {1'b0,1'b0,16'h0000};//空操作
parameter CMD_CLM = {1'b0,1'b0,16'h002A};//设置列起始和结束指令
parameter CMD_ROW = {1'b0,1'b0,16'h002B};//设置行起始和结束指令
parameter CMD_WMS = {1'b0,1'b0,16'h002C};//write memory start 开始写GRAM指令
assign index       = index_r;
assign write_ready = write_ready_r && ~(write_en && sop);
reg [17:0]  index_r;
reg         write_ready_r;
reg [9:0]   index_cnt;
reg [19:0]  pixels_cnt;//计数已经写入的像素数
reg [9:0]   width_r,height_r;//寄存每一帧图像的宽高
reg [15:0]  color_r;//缓存每帧第一个数据，因为sop到来时还不能立即写入显示屏，需要先配置x、y起止地址
wire [19:0] total_pixels_w;//一帧的总像素数
ili9488_mult u_ili9488_mult_0 (
	.clock(clk),
	.dataa(width_r),
	.datab(height_r),
	.result(total_pixels_w)
	);
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
    begin
	 index_r       <= CMD_NOP;
	 write_ready_r <= 1'b0;
	 index_cnt     <= 10'd0;
	 pixels_cnt    <= 20'd0;
	 width_r       <= 10'd0;
	 height_r      <= 10'd0;
	 color_r       <= 16'd0;
	 end
else
    begin
	 if(index_cnt == 10'd0)
	     index_cnt     <= (write_en && sop)?index_cnt+10'd1:index_cnt;
	 else if(index_cnt <= 10'd12)
	     index_cnt <= index_cnt+10'd1;
	 else if(index_cnt == 10'd13)
	     begin
		  if(pixels_cnt >= total_pixels_w-20'd1)
		      index_cnt <= 10'd0;
		  else
		      index_cnt <= index_cnt;
		  end
	 case(index_cnt)
	 10'd0:begin
	     index_r       <= CMD_NOP;
		  write_ready_r <= ~(write_en && sop);
		  color_r <= (write_en && sop)?color:color_r;
		  if(write_en && sop)
		      begin
				width_r  <= x_end-x_start+1'b1;
				height_r <= y_end-y_start+1'b1;
				end
		  else
		      begin
				width_r  <= width_r;
				height_r <= height_r;
				end
	 end
	 //设置列起始和结束
	 10'd1:index_r <= CMD_CLM;//设置列起始和结束
	 10'd2:index_r <= {1'b0,1'b1,14'd0,x_start[9:8]};//起始列地址高字节
	 10'd3:index_r <= {1'b0,1'b1,8'd0,x_start[7:0]};//起始列地址低字节
	 10'd4:index_r <= {1'b0,1'b1,14'd0,x_end[9:8]};//结束列地址高字节
	 10'd5:index_r <= {1'b0,1'b1,8'd0,x_end[7:0]};//结束列地址低字节
	 //设置行起始和结束
	 10'd6:index_r <= CMD_ROW;//设置行起始和结束
	 10'd7:index_r <= {1'b0,1'b1,14'd0,y_start[9:8]};//起始行地址高字节
	 10'd8:index_r <= {1'b0,1'b1,8'd0,y_start[7:0]};//起始行地址高字节
	 10'd9:index_r <= {1'b0,1'b1,14'd0,y_end[9:8]};//起始行地址高字节
	 10'd10:index_r <= {1'b0,1'b1,8'd0,y_end[7:0]};//起始行地址高字节
	 //开启写GRAM
	 10'd11:index_r <= CMD_WMS;//设置行起始和结束
	 10'd12:begin
	     index_r       <= {1'b0,1'b1,color_r};//补写第一个像素数据  
	     pixels_cnt    <= 20'd1;
	 end
	 10'd13:begin
	     if(pixels_cnt >= total_pixels_w-20'd1)
		      pixels_cnt <= 20'd0;
	     else if(write_en)
				pixels_cnt <= pixels_cnt+1'b1;
		  else
		      pixels_cnt <= pixels_cnt;
		  if(write_en && pixels_cnt >= total_pixels_w-20'd1)
		      write_ready_r <= 1'b0;
		  else
		      write_ready_r <= 1'b1;
	     index_r       <= {!write_en,1'b1,color};//写像素数据	  
	 end
	 endcase
	 end
end
endmodule 